import pymysql
from pymongo import MongoClient
from datetime import datetime, date
from decimal import Decimal
from config import MYSQL_CONFIG, MONGO_URI, MONGO_DB_NAME, SYNC_META_ID, BATCH_SIZE


def convert_decimal(obj):
    if isinstance(obj, dict):
        return {k: convert_decimal(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [convert_decimal(i) for i in obj]
    elif isinstance(obj, Decimal):
        return float(obj)
    elif isinstance(obj, date):
        # 解决date类型的异常
        return datetime.combine(obj, datetime.min.time())
    else:
        return obj


def perform_sync():
    mongo = MongoClient(MONGO_URI)
    db = mongo[MONGO_DB_NAME]
    meta = db["sync_metadata"]
    products_collection = db["products"]

    # 获取上次同步时间
    record = meta.find_one({"_id": SYNC_META_ID}) or {}
    last_sync_time = record.get("last_sync_time", "2023-01-01 00:00:00")

    try:
        conn = pymysql.connect(**MYSQL_CONFIG, cursorclass=pymysql.cursors.DictCursor)
        cursor = conn.cursor()

        # 获取总待同步数量
        cursor.execute("SELECT COUNT(*) AS count FROM products WHERE updated_at > %s", (last_sync_time,))
        total = cursor.fetchone()["count"]
        print(f"同步任务启动：共 {total} 条待处理")

        synced = 0
        for offset in range(0, total, BATCH_SIZE):
            cursor.execute(
                """
                SELECT * FROM products
                WHERE updated_at > %s
                ORDER BY updated_at ASC
                LIMIT %s OFFSET %s
            """,
                (last_sync_time, BATCH_SIZE, offset),
            )
            batch = cursor.fetchall()

            for product in batch:
                product_id = product["id"]

                # 品牌
                cursor.execute("SELECT * FROM brands WHERE id = %s", (product["brand_id"],))
                brand = cursor.fetchone()

                # 价格
                cursor.execute("SELECT * FROM prices WHERE product_id = %s", (product_id,))
                price = cursor.fetchone()

                # 图片
                cursor.execute("SELECT type, url FROM product_images WHERE product_id = %s", (product_id,))
                images = cursor.fetchall()

                # 库存
                cursor.execute(
                    """
                    SELECT warehouse_id, stock, in_transit, eta, eta_date
                    FROM stocks WHERE product_id = %s
                """,
                    (product_id,),
                )
                stocks = cursor.fetchall()

                # 构造文档
                doc = {
                    "product_id": product_id,
                    "name": product["name"],
                    "code": product["code"],
                    "brand_info": brand,
                    "price_info": price,
                    "images": images,
                    "stock_details": stocks,
                    "unit": product["unit"],
                    "volume_rate": product["volume_rate"],
                    "category": product["category"],
                    "department_id": product["department_id"],
                    "product_size_code_id": product["product_size_code_id"],
                    "info": {"type": product["info_type"], "id": product["info_id"]},
                    "tags": [product["tag1"], product["tag2"], product["tag3"], product["tag4"]],
                    "manufacturer": product["manufacturer"],
                    "status_flags": {
                        "is_customer_show": product["is_customer_show"],
                        "is_special_offer": product["is_special_offer"],
                        "is_clearance": product["is_clearance"],
                        "is_active": product["is_active"],
                        "is_deleted": product["is_deleted"],
                        "is_sold": product["is_sold"],
                        "is_purchased": product["is_purchased"],
                        "xero_state": product["xero_state"],
                        "xero_archived": product["xero_archived"],
                    },
                    "stock_summary": {
                        "total_stock": product["total_stock"],
                        "total_in_transit": product["total_in_transit"],
                        "stock_3rdP": product["stock_3rdP"],
                    },
                    "guid": product["guid"],
                    "created_at": product["created_at"],
                    "updated_at": product["updated_at"],
                }

                doc = convert_decimal(doc)

                products_collection.replace_one({"product_id": product_id}, doc, upsert=True)
                synced += 1

        now = datetime.utcnow()
        meta.update_one(
            {"_id": SYNC_META_ID},
            {
                "$set": {
                    "last_sync_time": now,
                    "last_success": now,
                    "status": "idle",
                    "total_synced": record.get("total_synced", 0) + synced,
                    "error": None,
                }
            },
            upsert=True,
        )

        print(f"同步完成，成功同步 {synced} 条")

    except Exception as e:
        meta.update_one(
            {"_id": SYNC_META_ID},
            {"$set": {"status": "failed", "last_failure": datetime.utcnow(), "error": str(e)}},
            upsert=True,
        )
        print(f"同步失败：{e}")

    finally:
        try:
            cursor.close()
            conn.close()
        except:
            pass
